/*
 *    Copyright 2022 The DSMS Authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.dsms.modules.storagepool.task;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dsms.common.constant.CrushmapConst;
import com.dsms.common.constant.ResultCode;
import com.dsms.common.constant.TaskStatusEnum;
import com.dsms.common.constant.TaskTypeEnum;
import com.dsms.common.remotecall.model.RemoteResponse;
import com.dsms.common.taskmanager.TaskStrategy;
import com.dsms.common.taskmanager.model.Step;
import com.dsms.common.taskmanager.model.Task;
import com.dsms.common.taskmanager.service.IStepService;
import com.dsms.common.taskmanager.service.ITaskService;
import com.dsms.dfsbroker.osd.crushmap.api.CrushmapApi;
import com.dsms.dfsbroker.osd.crushmap.request.DelBucketRequest;
import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolNodeManageDTO;
import com.dsms.modules.util.RemoteCallUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.List;


@Slf4j
@Service(TaskTypeEnum.TypeConstants.POOL_REMOVE_NODE)
public class StoragePoolRemoveNodeTask implements TaskStrategy {

    private final CrushmapApi crushmapApi;
    private final ITaskService taskService;
    private final IStepService stepService;
    private final GetCrushmapStepResult getCrushmapStepResult;

    @Autowired
    public StoragePoolRemoveNodeTask(CrushmapApi crushmapApi, ITaskService taskService, IStepService stepService, GetCrushmapStepResult getCrushmapStepResult) {
        this.crushmapApi = crushmapApi;
        this.taskService = taskService;
        this.stepService = stepService;
        this.getCrushmapStepResult = getCrushmapStepResult;
    }

    @Override
    public Task execute(Task task) {
        String taskParam = task.getTaskParam();
        if (ObjectUtils.isEmpty(taskParam)) {
            task.setTaskEndTime(LocalDateTime.now());
            task.setTaskErrorMessage("task parameter is null");
            task.setTaskStatus(TaskStatusEnum.FAIL.getStatus());
            return task;
        }
        StoragePoolNodeManageDTO storagePoolNodeManageDTO = JSONUtil.toBean(taskParam, StoragePoolNodeManageDTO.class);
        //get step task
        Integer taskId = task.getId();
        List<Step> steps = stepService.list(new LambdaQueryWrapper<Step>().eq(Step::getTaskId, taskId));
        for (Step step : steps) {
            String nodeName = step.getStepParam();
            //construct the host bucket name. example: pool1_node1
            String hostBucketName = storagePoolNodeManageDTO.getPoolName() + CrushmapConst.BUCKET_NAME_CONNECTOR + nodeName;
            try {
                //delete bucket in crushmap
                RemoteResponse response = crushmapApi.delBucket(RemoteCallUtil.generateRemoteRequest(), hostBucketName);
                getCrushmapStepResult.getStepResponse(step, response, DelBucketRequest.DELETE_BUCKET_SUCCESS, ResultCode.POOL_REMOVENODE_ERROR.getMessage());
            } catch (Throwable e) {
                task.setTaskEndTime(LocalDateTime.now());
                task.setTaskStatus(TaskStatusEnum.FAIL.getStatus());
                task.setTaskErrorMessage(e.getMessage());
                return task;
            }
        }
        task.setTaskEndTime(LocalDateTime.now());
        task.setTaskStatus(TaskStatusEnum.FINISH.getStatus());
        return task;
    }

    @Override
    public boolean validateTask(String[] validateParam) {
        return taskService.validateTaskMessageAndTaskType(validateParam[0]);
    }

}

